package tailfile

import (
	"github.com/sirupsen/logrus"
	"logAgent/common"
)

//tail task管理结构体
type tailTaskMgr struct {
	tailTaskMap map[string]*tailTask   //task任务map，只有是启动的都会放到这个map中用于管理
	collectEntrylist []common.CollectEntry   //所有配置项
	confChan chan []common.CollectEntry    //等待修改后新配置的通道

}
var (
	ttMgr *tailTaskMgr
)

func Init(allConfig []common.CollectEntry)(err error) {
	// allConf里面存了若干个日志的收集项,
	// 针对每一个日志收集项创建一个对应的tailObj

	ttmgr := tailTaskMgr{
		tailTaskMap: make(map[string]*tailTask, 20),
		collectEntrylist : allConfig,
		confChan: make(chan []common.CollectEntry),  //建一个阻塞的无缓冲通道
	}
	//循环读取conf配置信息
	for _, conf := range allConfig {
		//每读一个就初始化一个tailtask对象
		tt := NewTailTask(conf.Path, conf.Topic)
		ttmgr.tailTaskMap[conf.Path] = tt   //把每个task任务都放到map中管理
		//读文件
		err := tt.init()
		if err != nil {
			logrus.Errorf("create tailObj for path:%s failed, err:%v", conf.Path, err)
			continue
		}
		//把此task的msg发送到msgChan中
		go tt.run()
	}
	//新启一个进程，后台一直循环等待新的配置信息来
	go ttmgr.Watch()
	return
}

func(t *tailTaskMgr) Watch() {
	for{
		//如果有配置信息更新的话就会发送到这里，往下走，没有的话就会阻塞不会执行后面的代码
		newConf := <-t.confChan
		//配置更新后要重新管理之前的task
		logrus.Infof("get new conf from etcd, conf:%v, start manage tailTask...", newConf)
		for _, conf := range newConf {
			//原来已经存在的任务不用动
			if t.isExist(conf) {
				continue
			}
			//原来没有的要新启一个task
			tt := NewTailTask(conf.Path, conf.Topic)
			t.tailTaskMap[conf.Path] = tt   //把每个task任务都放到map中管理
			//读文件
			err := tt.init()
			if err != nil {
				logrus.Errorf("create tailObj for path:%s failed, err:%v", conf.Path, err)
				continue
			}
			//把此task的msg发送到msgChan中
			go tt.run()
		}
		//原来有，现在没有的task要停掉
		for key, task := range t.tailTaskMap {
			var found bool
			//有的话不做处理
			for _, conf := range newConf {
				if key == conf.Path {
					found = true
					break
				}
			}
			//没有的话就停掉，并在map中删除此管理的task
			if !found {
				task.cancel()
				delete(t.tailTaskMap, key) // 从管理类中删掉
				logrus.Infof("the task collect path:%s need to stop.", task.path)
			}
		}
	}
}


// 判断tailTaskMap中是否存在该收集项
func (t *tailTaskMgr) isExist(conf common.CollectEntry) bool {
	_, ok := t.tailTaskMap[conf.Path]
	return ok
}


func SendNewConf(newConf []common.CollectEntry) {
	ttMgr.confChan <- newConf
}